package com.frank.loadinglibrary.special.element;

import com.frank.loadinglibrary.base.baseanimations.BaseAnimationController;
import com.frank.loadinglibrary.base.baseelement.BaseElement;
import com.frank.loadinglibrary.base.baseelement.IComponentCallback;
import com.frank.loadinglibrary.special.cool.ball.*;
import com.frank.loadinglibrary.special.cool.letter.*;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;

import java.util.ArrayList;
import java.util.List;

/**
 * @author SUQI
 * @date 2021/6/4
 * @description
 **/
public class CoolLoadingElement extends BaseElement implements BaseAnimationController.IAnimationController<AnimatorValue>, CoolBall.AnimatorStateListen, BaseLetter.AnimationCallBack {

    //颜色值数据
    public final static Color GREEN = new Color(Color.getIntColor("#5eb752"));
    public final static Color YELLOW = new Color(Color.getIntColor("#fde443"));
    public final static Color BLUE = new Color(Color.getIntColor("#21bbfc"));
    public final static Color RED = Color.RED;
    public final static Color TRANSPARENT = new Color(Color.getIntColor("#0021bbfc"));
    public final static Color WHITE = Color.WHITE;

    private float mCenterX;
    private float mCenterY;

    private boolean isInit = false;


    private List<CoolBall> mPellets;
    private List<BaseLetter> mLetters;
    private int mEndNum = 0;
    private boolean isEnding = false;
    private int mLetterEndNum = 0;

    private CoolLoadingElement(IComponentCallback iComponentCallback) {
        this.callback = iComponentCallback;
    }

    @Override
    public ArrayList<AnimatorValue> onCreateAnimators() {
        ArrayList<AnimatorValue> list = new ArrayList<>();
        AnimatorValue mAnimator = new AnimatorValue();
        mAnimator.setDuration(16);
        mAnimator.setLoopedCount(Animator.INFINITE);
        mAnimator.setLoopedListener(animator -> callback.reflushComponent());
        list.add(mAnimator);
        return list;
    }

    @Override
    public void onAnimationReset() {
        //do nothing because donot need to reset animation params
    }

    @Override
    public BaseAnimationController.IAnimationController<AnimatorValue> initAnimationController() {
        return this;
    }

    @Override
    public void initPaint() {
        super.initPaint();
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        if (!isInit) {
            init();
            isInit = true;
        } else {
            drawTheWorld(canvas);
        }
    }

    private void init() {
        mPellets = new ArrayList<>();
        mLetters = new ArrayList<>();

        mCenterX = getWidth() / 2f;
        mCenterY = getHeight() / 2f;

        initComponents(mCenterX, mCenterY);

    }

    /**
     * 初始化各个组件,包括球和字
     */
    public void initComponents(float x, float y) {
        // 加入小球
        this.addBall(new FirstCoolBall(x - 180, y));
        this.addBall(new ForthCoolBall(x + 180, y));
        this.addBall(new ThirdCoolBall(x + 60, y));
        this.addBall(new SecCoolBall(x - 60, y));
        // 为小球添加结束动画监听
        for (CoolBall p : mPellets) {
            p.setAnimatorStateListen(this);
        }
        // 加入字母
        this.addLetter(new LLetter(x - 325, y));
        this.addLetter(new OLetter(x - 205, y));
        this.addLetter(new ALetter(x - 85, y));
        this.addLetter(new DLetter(x + 35, y));
        this.addLetter(new ILetter(x + 125, y));
        this.addLetter(new NLetter(x + 205, y));
        this.addLetter(new GLetter(x + 325, y));


        for (BaseLetter p : mLetters) {
            p.setAnimationCallBack(this);
        }

        startPelletsAnim();
    }

    /**
     * 开始小球的动画
     */
    public void startPelletsAnim() {
        isEnding = false;
        mEndNum = 0;

        for (CoolBall p : mPellets) {
            p.startAnim();
        }
    }

    /**
     * 先进行小球的移动,同时小球进行结尾动画展示,当完成以为,小球结尾动画继续,同时开始文字的展示
     */
    public void showText() {
        isEnding = true;
        mEndNum = 0;
        for (CoolBall p : mPellets) {
            p.endAnim();
        }
    }

    public void addBall(CoolBall pellet) {
        if (pellet != null) {
            mPellets.add(pellet);
            pellet.prepareAnim();
        }
    }

    public void addLetter(BaseLetter letter) {
        if (letter != null) {
            mLetters.add(letter);
        }
    }

    public void drawTheWorld(Canvas canvas) {
        for (CoolBall p : mPellets) {
            p.drawSelf(canvas);
        }

        for (BaseLetter l : mLetters) {
            l.drawSelf(canvas);
        }
    }

    public void endAnim() {
        isEnding = true;
    }

    // 纪录动画结束的小球个数,当动画结束可以执行循环任务
    @Override
    public void onAnimatorEnd() {
        mEndNum++;
        if (mEndNum == mPellets.size()) {
            endAnim();
            if (isEnding) {
                showText();
            } else {
                startPelletsAnim();
            }
        }
    }

    // 在小球移动到适合的位置后,字母出现
    @Override
    public void onMoveEnd() {
        mEndNum++;
        if (mEndNum == mPellets.size()) {
            for (BaseLetter l : mLetters) {
                l.startAnim();
            }
        }
    }

    /**
     * 由第一个小球传达结束动画消息到manager中
     */
    @Override
    public void onAllAnimatorEnd() {
        onAnimatorEnd();
    }


    @Override
    public void onLetterAnimatorEnd() {
        mLetterEndNum++;
        if (mLetterEndNum == mLetters.size()) {
            mLetterEndNum = 0;
            //动画结束
            callback.getContext().getMainTaskDispatcher().delayDispatch(() -> {

                for (CoolBall p : mPellets) {
                    p.reset();
                }
                for (BaseLetter l : mLetters) {
                    l.reset();
                }
                isEnding = false;
                startPelletsAnim();
            }, 1000);
        }
    }

    public static class CoolLoadingBuilder {
        private IComponentCallback iComponentCallback;

        public CoolLoadingBuilder(IComponentCallback iComponentCallback) {
            this.iComponentCallback = iComponentCallback;
        }

        public CoolLoadingElement build() {
            return new CoolLoadingElement(iComponentCallback);
        }
    }
}
